﻿using System;
using System.Collections.Generic;
using System.Linq;
using RenRen.Schema;
using RenRen.Session;
using RenRen.Utility;
using RenRen.Common;

namespace RenRen.Rest {
    /// <summary>
    /// 通知和email接口
    /// </summary>
    public class Notifications : RestBase {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="session"></param>
        public Notifications( RenRenSession session)
            : base(session) {
        }

        /// <summary>
        /// 给当前登录者的好友或也安装了同样应用的用户发通知。
        /// 分发继续考虑应用的评分、通知的屏蔽和通知的举报这些因素，没有发送总量的限制，
        /// 每一个应用通知的分发分为appToUser和UserToUser两种方式，这次更新暂时不开放appToUser。 
        /// UserToUser：每个app的每一个安装用户(sender)每一天有一定配额（可以通过admin.getAllocation接口取到这个配额）。
        /// 接收者（receiver）必须是用户的好友或者是安装应用的用户。没有通过审核的app，通知只发送给发送者，默认配额数量为20条
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <returns>好友ID集合</returns>
        /// <remarks></remarks>
        public bool Send(string notification) {
            return Send(new int[] {}, notification);
        }

        /// <summary>
        /// 给当前登录者的好友或也安装了同样应用的用户发通知。
        /// 分发继续考虑应用的评分、通知的屏蔽和通知的举报这些因素，没有发送总量的限制，
        /// 每一个应用通知的分发分为appToUser和UserToUser两种方式，这次更新暂时不开放appToUser。 
        /// UserToUser：每个app的每一个安装用户(sender)每一天有一定配额（可以通过admin.getAllocation接口取到这个配额）。
        /// 接收者（receiver）必须是用户的好友或者是安装应用的用户。没有通过审核的app，通知只发送给发送者，默认配额数量为20条
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <returns>好友ID集合</returns>
        /// <remarks></remarks>
        public bool Send(int uid, string notification) {
            return Send(new int[]{uid}, notification);
        }

        /// <summary>
        /// 得到当前登录用户的好友列表，得到的只是含有好友uid的列表
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <param name="callback">异步回调代理</param>
        /// <param name="state">异步调用状态对象</param>        
        public void SendAsync(string notification, SendCallback callback, Object state) {
            Send(new int[] { }, notification, true, callback, state);
        }

        /// <summary>
        /// 给当前登录者的好友或也安装了同样应用的用户发通知。
        /// 分发继续考虑应用的评分、通知的屏蔽和通知的举报这些因素，没有发送总量的限制，
        /// 每一个应用通知的分发分为appToUser和UserToUser两种方式，这次更新暂时不开放appToUser。 
        /// UserToUser：每个app的每一个安装用户(sender)每一天有一定配额（可以通过admin.getAllocation接口取到这个配额）。
        /// 接收者（receiver）必须是用户的好友或者是安装应用的用户。没有通过审核的app，通知只发送给发送者，默认配额数量为20条
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <remarks></remarks>
        public bool Send(int[] uids, string notification) {
            return Send(uids, notification, false, null, null);
        }

        /// <summary>
        /// 得到当前登录用户的好友列表，得到的只是含有好友uid的列表
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <param name="callback">异步回调代理</param>
        /// <param name="state">异步调用状态对象</param>        
        public void SendAsync(int uid, string notification, SendCallback callback, Object state) {
            Send(new int[]{uid}, notification, true, callback, state);
        }

        /// <summary>
        /// 得到当前登录用户的好友列表，得到的只是含有好友uid的列表
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <param name="callback">异步回调代理</param>
        /// <param name="state">异步调用状态对象</param>        
        public void SendAsync(int[] uids, string notification,SendCallback callback, Object state) {
            Send(uids, notification, true , callback , state );
        }


        /// <summary>
        /// 给当前登录者的好友或也安装了同样应用的用户发通知。
        /// 分发继续考虑应用的评分、通知的屏蔽和通知的举报这些因素，没有发送总量的限制，
        /// 每一个应用通知的分发分为appToUser和UserToUser两种方式，这次更新暂时不开放appToUser。 
        /// UserToUser：每个app的每一个安装用户(sender)每一天有一定配额（可以通过admin.getAllocation接口取到这个配额）。
        /// 接收者（receiver）必须是用户的好友或者是安装应用的用户。没有通过审核的app，通知只发送给发送者，默认配额数量为20条
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <returns>好友ID集合</returns>
        /// <remarks></remarks>
        public bool SendEmail(int template_id, string body_data) {
            return SendEmail(new int[] { },template_id, body_data);
        }

        /// <summary>
        /// 给当前登录者的好友或也安装了同样应用的用户发通知。
        /// 分发继续考虑应用的评分、通知的屏蔽和通知的举报这些因素，没有发送总量的限制，
        /// 每一个应用通知的分发分为appToUser和UserToUser两种方式，这次更新暂时不开放appToUser。 
        /// UserToUser：每个app的每一个安装用户(sender)每一天有一定配额（可以通过admin.getAllocation接口取到这个配额）。
        /// 接收者（receiver）必须是用户的好友或者是安装应用的用户。没有通过审核的app，通知只发送给发送者，默认配额数量为20条
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <returns>好友ID集合</returns>
        /// <remarks></remarks>
        public bool SendEmail(int uid, int template_id, string body_data) {
            return SendEmail(new int[] { uid }, template_id, body_data);
        }

        /// <summary>
        /// 得到当前登录用户的好友列表，得到的只是含有好友uid的列表
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <param name="callback">异步回调代理</param>
        /// <param name="state">异步调用状态对象</param>        
        public void SendEmailAsync(int template_id, string body_data, SendEmailCallback callback, Object state) {
            SendEmail(new int[] { }, template_id, body_data, true, callback, state);
        }

        /// <summary>
        /// 给当前登录者的好友或也安装了同样应用的用户发通知。
        /// 分发继续考虑应用的评分、通知的屏蔽和通知的举报这些因素，没有发送总量的限制，
        /// 每一个应用通知的分发分为appToUser和UserToUser两种方式，这次更新暂时不开放appToUser。 
        /// UserToUser：每个app的每一个安装用户(sender)每一天有一定配额（可以通过admin.getAllocation接口取到这个配额）。
        /// 接收者（receiver）必须是用户的好友或者是安装应用的用户。没有通过审核的app，通知只发送给发送者，默认配额数量为20条
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <remarks></remarks>
        public bool SendEmail(int[] uids, int template_id, string body_data ) {
            return SendEmail(uids,template_id, body_data, false, null, null);
        }

        /// <summary>
        /// 得到当前登录用户的好友列表，得到的只是含有好友uid的列表
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <param name="callback">异步回调代理</param>
        /// <param name="state">异步调用状态对象</param>        
        public void SendEmailAsync(int uid, int template_id, string body_data, SendEmailCallback callback, Object state) {
            SendEmail(new int[] { uid }, template_id, body_data, true, callback, state);
        }

        /// <summary>
        /// 得到当前登录用户的好友列表，得到的只是含有好友uid的列表
        /// </summary>
        /// <param name="uids">这些用户必须是当前登录者的好友或也安装了此应用。
        /// 请确保一次传入的用户id数少于20个。
        /// 如果要给当前用户发送通知，
        /// 请指定此参数值为空串</param>
        /// <param name="notification">通知的内容，可以是XNML类型的文本信息，支持的XNML有<xn:name/>和<a/>，</param>
        /// <param name="callback">异步回调代理</param>
        /// <param name="state">异步调用状态对象</param>        
        public void SendEmailAsync(int[] uids, int template_id, string body_data, SendEmailCallback callback, Object state) {
            SendEmail(uids, template_id, body_data, true, callback, state);
        }



        private bool Send(int[] uid, string notification, bool isAsync, SendCallback callback, Object state) {
            var parameterList = new Dictionary<string, string> { { "method", "xiaonei.notifications.send" } };
            Utilities.AddOptionalParameter(parameterList, "to_ids", uid.AsString());
            Utilities.AddOptionalParameter(parameterList, "notification", notification);

            if (isAsync) {
                SendRequestAsync<notifications_send_response, notifications_send_response>(parameterList, HasSession, new RenRenCallCompleted<notifications_send_response>(callback), state);
                return false;
            }

            var response = SendRequest<notifications_send_response>(parameterList, HasSession);
            return response != null  ? true :false ;
        }

        private bool SendEmail(int[] recipients, int template_id,string body_data, bool isAsync, SendEmailCallback  callback, Object state) {
            var parameterList = new Dictionary<string, string> { { "method", "xiaonei.notifications.send" } };
            Utilities.AddOptionalParameter(parameterList, "to_ids", recipients.AsString());
            Utilities.AddOptionalParameter(parameterList, "template_id", template_id.ToString());
            Utilities.AddOptionalParameter(parameterList, "body_data", body_data);
            if (isAsync) {
                SendRequestAsync<notifications_sendEmail_response, notifications_sendEmail_response >(parameterList, HasSession, new RenRenCallCompleted<notifications_sendEmail_response >(callback), state);
                return false;
            }

            var response = SendRequest<notifications_sendEmail_response>(parameterList, HasSession);
            return response != null ? true : false;
        }

        #region 代理
        /// <summary>
        /// 发送通知调用完成代理
        /// </summary>
        /// <param name="status">是否发送成功</param>
        /// <param name="state">异步请求状态</param>
        /// <param name="e">异常对象</param>
        public delegate void SendCallback(notifications_send_response status, Object state, RenRenException e);
        /// <summary>
        /// 发送邮件调用完成代理
        /// </summary>
        /// <param name="status">是否发送成功</param>
        /// <param name="state">异步请求状态</param>
        /// <param name="e">异常对象</param>
        public delegate void SendEmailCallback(notifications_sendEmail_response status, Object state, RenRenException e);
        #endregion Delegates
    }
}
